package DTO;

import java.lang.reflect.Array;
import java.util.ArrayList;

import org.Globals;
import org.sqlStatements;

import CustomUI.DrawingSurface;
import CustomUI.LayerView;
import GameTools.ydPoint;
import android.R.bool;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Path;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;

public class LayerDTO extends BaseDTO {

	static SQLiteDatabase db = Globals.sqlDB;
	public int lid;
	public int did;
	public int zindex;

	ArrayList<DrawingCmdDTO> drawingsCmds;

	public static Context mContext;
	LayerView LV;

	// TODO not implemented yet
	int largerestInstruc = -1;

	public LayerDTO(int did, int instrucNum, SQLiteDatabase db, DrawingSurface drawingSurface, int zindex) {
		LayerDTO.db = db;
		this.did = did;
		this.zindex=zindex;
		ContentValues values = new ContentValues();
		values.put(sqlStatements.DID, did);
		values.put(sqlStatements.ZINDEX, zindex);
		lid = (int) db.insert(sqlStatements.LAYERS, null, values);

		LV = new LayerView(mContext);
		drawingSurface.addLayerView(LV);
		LV.invalidate();
		drawingSurface.invalidate();
		
		/*ArrayList<ydPoint> coordinates;
		coordinates = new ArrayList<ydPoint>();
		coordinates.add(new ydPoint());

		DrawingCmdDTO DC = new DrawingCmdDTO();
		DC.setCommand(sqlStatements.DC_CREATE_LAYER);
		DC.setCoordinates(coordinates);
		DC.setInstructNum(instrucNum);
		DC.setLid(lid);
		LV.setId(lid);

		drawingsCmds = new ArrayList<DrawingCmdDTO>();

		addDC(DC);*/

		return;
	}

	public int getZindex() {
		return zindex;
	}

	public void setZindex(int zindex) {
		this.zindex = zindex;
	}

	public void CreateFirstCMD(int instrucNum) {
		ArrayList<ydPoint> coordinates;
		coordinates = new ArrayList<ydPoint>();
		coordinates.add(new ydPoint());

		DrawingCmdDTO DC = new DrawingCmdDTO();
		DC.setCommand(sqlStatements.DC_CREATE_LAYER);
		DC.setCoordinates(coordinates);
		DC.setInstructNum(instrucNum);
		DC.setLid(lid);
		LV.setId(lid);

		drawingsCmds = new ArrayList<DrawingCmdDTO>();

		addDC(DC);
	}

	public LayerView getLV() {
		return LV;
	}

	public void setLV(LayerView lV) {
		LV = lV;
	}

	public LayerDTO(SQLiteDatabase db) {
		LayerDTO.db = db;
	}

	public LayerDTO() {
		// TODO Auto-generated constructor stub
	}

	public int draw(int lastState) {
		if(LV==null){
			newLV();
		}
		int foundAt=-1;
		DrawingCmdDTO d;
		for (int i = 0; i < drawingsCmds.size(); i++) {
			d = drawingsCmds.get(i);
			if(d.getInstructNum()<lastState){
				foundAt=i;
			}
			else if(d.getInstructNum()>=lastState){
				break;
			}
		}
		
		if(foundAt!=-1){
			d=drawingsCmds.get(foundAt);
			LV.draw(d);
		}
		
		return foundAt;
		
	}

	public void drawAll() {
		if(LV==null){
			newLV();
		}
		LV.draw(drawingsCmds);

	}

	private void newLV() {
		LV=new LayerView(LayerDTO.mContext);
		LV.setId(lid);
		
	}

	public void addDC(DrawingCmdDTO dC) {

		removeCMDAndAfter(dC);
		drawingsCmds.add(dC);
		drawAll();

	}

	public void addDC(DrawingCmdDTO dC, boolean redraw) {
		removeCMDAndAfter(dC);
		drawingsCmds.add(dC);
		if(redraw){
			drawAll();
		}
		else{
			dC.insertUpdate();
		}
		
	}

	public void removeCMDAndAfter(DrawingCmdDTO dC) {
		new MyAsyncTask().execute(dC);
		removeCMDAndAfterInArray(dC);
	}

	private void removeCMDAndAfterInArray(DrawingCmdDTO dC) {
		ArrayList<DrawingCmdDTO> DCS = (ArrayList<DrawingCmdDTO>) drawingsCmds
				.clone();
		for (DrawingCmdDTO d : DCS) {
			if (d.instructNum >= dC.instructNum)
				drawingsCmds.remove(d);
		}

	}

	public int getLid() {
		return lid;
	}

	public void setLid(int lid) {
		this.lid = lid;
	}

	public NextStep Undo(int currentInstruct) {
		Boolean rtn = false;
		NextStep ns = new NextStep();
		DrawingCmdDTO newCurrent = null;
		Boolean exists = false;
		for (DrawingCmdDTO d : drawingsCmds) {
			if (d.instructNum == currentInstruct) {
				exists = true;
				ns.setId(lid);
				ns.setIsThis(true);
				ns.setAction(NextStep.UPDATE);
				if (d.command.equals(sqlStatements.DC_CREATE_LAYER)) {
					LayerView.drawingSurface.removeLayerView(LV);
					ns.setAction(NextStep.DELETE);

					rtn = true;
				} else if (d.command.equals(sqlStatements.DC_MOVE_UP)) {

					ns.setAction(NextStep.MOVE_DOWN);

					rtn = true;
				} else if (d.command.equals(sqlStatements.DC_MOVE_DOWN)) {
					ns.setAction(NextStep.MOVE_UP);

					rtn = true;
				}
				else if(d.command.equals(sqlStatements.DC_DELETE_LAYER)){
					ns.setAction(NextStep.ADD);
					LayerView.drawingSurface.addLayerView(LV);
					rtn = true;
				}
			}
			if (d.instructNum < currentInstruct) {
				if (newCurrent == null)
					newCurrent = d;
				else if (d.instructNum > newCurrent.instructNum) {
					newCurrent = d;
				}
			}
		}
		if (exists && newCurrent != null) {
			LV.draw(newCurrent);
		}
		return ns;
	}

	public NextStep Redo(int currentInstruct) {
		Boolean rtn = false;
		DrawingCmdDTO newCurrent = null;
		NextStep ns = new NextStep();
		Boolean exists = false;
		for (DrawingCmdDTO d : drawingsCmds) {
			if (d.instructNum == currentInstruct) {
				exists = true;
				ns.setId(lid);
				ns.setIsThis(true);
				ns.setAction(NextStep.UPDATE);
				if (d.command.equals(sqlStatements.DC_CREATE_LAYER)) {
					LayerView.drawingSurface.addLayerView(LV);
					ns.setAction(NextStep.ADD);
					rtn = true;

				} 
				else if (d.command.equals(sqlStatements.DC_MOVE_UP)) {

					ns.setAction(NextStep.MOVE_UP);

					rtn = true;
				} else if (d.command.equals(sqlStatements.DC_MOVE_DOWN)) {
					ns.setAction(NextStep.MOVE_DOWN);

					rtn = true;
				}else if(d.command.equals(sqlStatements.DC_DELETE_LAYER)){
					ns.setAction(NextStep.DELETE);
					LayerView.drawingSurface.removeLayerView(LV);
					rtn = true;
				}
				else {
					LV.draw(d);
				}
			}
			if (d.instructNum > currentInstruct) {
				if (newCurrent == null)
					newCurrent = d;
				else if (d.instructNum < newCurrent.instructNum) {
					newCurrent = d;
				}
			}
		}
		/*
		 * if (exists && newCurrent != null) { LV.draw(newCurrent); } if
		 * (newCurrent != null) { if
		 * (newCurrent.command.equals(sqlStatements.DC_CREATE_LAYER)) {
		 * LayerView.drawingSurface.addView(LV); ns.setAction(NextStep.ADD); rtn
		 * = true; } }
		 */
		return ns;
	}

	public Bitmap getImage() {
		return drawingsCmds.get(drawingsCmds.size() - 1).getImage();
	}

	public Bitmap getImage(int currentInstruct) {
		for (DrawingCmdDTO d : drawingsCmds) {
			if (d.instructNum == currentInstruct - 1) {
				return d.getImage();
			}
		}
		return null;
	}

	public Bitmap getImageBefore(int currentInstruct) {
		int x = -1;
		for (DrawingCmdDTO d : drawingsCmds) {
			if (d.instructNum == currentInstruct) {
				return drawingsCmds.get(x).getImage();
			}
			else{
				x++;
			}
		}
		return null;
	}

	public static ArrayList<LayerDTO> getLayers(int did, SQLiteDatabase sqlDB) {
		
		ArrayList<LayerDTO> results=new ArrayList<LayerDTO>();
		
		try {
			Cursor c = null;
			c = sqlDB.query(sqlStatements.LAYERS,
					new String[]{sqlStatements.LID}, sqlStatements.DID+"=?", new String[]{did+""},
					"", "", sqlStatements.ZINDEX);

			if (c != null) {
				LayerDTO l; 
				while (c.moveToNext()) {
					l=new LayerDTO();
					l.setDid(did);
					l.setLid(c.getInt(0));
					l.setDrawingsCmds(DrawingCmdDTO.getDrawingCmds(l.getLid(), sqlDB));
					l.newLV();
					results.add(l);
				}
			} else {
				Log.d("",
						"== something happened, could not extract from database");
			}
			if (c != null) {
				c.close();
			} else {
				Log.d("", "== c was null");
			}
		} catch (Exception e) {
			e.printStackTrace();
			Log.d("", "== something went wrong");
		}
		return results;
	}

	public int getDid() {
		return did;
	}

	public void setDid(int did) {
		this.did = did;
	}

	public ArrayList<DrawingCmdDTO> getDrawingsCmds() {
		return drawingsCmds;
	}

	public void setDrawingsCmds(ArrayList<DrawingCmdDTO> drawingsCmds) {
		this.drawingsCmds = drawingsCmds;
	}

	public void updateZIndex() {
		ContentValues values = new ContentValues();
		values.put(sqlStatements.ZINDEX, zindex);

		Globals.sqlDB.update(sqlStatements.LAYERS, values, sqlStatements.LID
				+ "=?", new String[] { lid + "" });
		
	}

	public void transform(int type, int t, int from, int to) {
		LV.transform(type, t, from, to);
		
	}

	public void ConfirmClicked() {
		LV.ConfirmClicked();
		
		
	}

	public void setImage(Bitmap image) {
		LV.setmCurrentDraw(image);
		
	}

	public void CancelClicked() {
		LV.CancelClicked();
		
	}

	public void erase(Path currentPath) {
		LV.erase(currentPath);
		
	}

}

class MyAsyncTask extends AsyncTask<Object, Void, Boolean> {
	@Override
	protected Boolean doInBackground(Object... objs) {
		// TODO Auto-generated method stub
		DrawingCmdDTO.deleteAndAfter(((DrawingCmdDTO) objs[0]).lid,
				((DrawingCmdDTO) objs[0]).instructNum);
		return true;
	}

	protected void onPostExecute(Double result) {

	}

	protected void onProgressUpdate(Integer... progress) {

	}
}
